package com.richard.base.ext

import android.annotation.SuppressLint
import android.app.Activity
import android.app.ActivityManager
import android.content.ClipData
import android.content.Context
import android.net.ConnectivityManager
import android.os.Build
import android.os.Process
import android.provider.Settings
import android.text.TextUtils
import android.view.View
import androidx.annotation.RequiresApi
import com.richard.base.common.activityManager
import com.richard.base.common.clipboardManager
import com.richard.base.common.connectivityManager
import java.util.ArrayList
import kotlin.system.exitProcess

/**
 ***************************************
 * 项目名称:ks-base-lib
 * @Author jiaruihua
 * 邮箱：jiaruihua@ksjgs.com
 * 创建时间: 2020/6/4     11:08 AM
 * 用途:
 ***************************************
 */

/**
 * 判断设备是否安装微信APP
 *
 * @return boolean
 */
fun Context.isWeixinAvilible(): Boolean {
    val pinfo = packageManager.getInstalledPackages(0)// 获取所有已安装程序的包信息
    if (pinfo != null) {
        for (i in pinfo.indices) {
            val pn = pinfo[i].packageName
            if ("com.tencent.mm" == pn) {
                return true
            }
        }
    }
    return false
}

/**
 * 是否有网络连接
 * @receiver Context
 * @return Boolean
 */
@SuppressLint("MissingPermission")
fun Context.isNetworkAvailable(): Boolean {
    val mNetworkInfo = connectivityManager?.activeNetworkInfo
    return mNetworkInfo != null && mNetworkInfo.isAvailable
}

/**
 * 检测网络是否是Mobile
 *
 * @return
 */
fun Context.isMobile(): Boolean {
    val mNetworkInfo = connectivityManager?.activeNetworkInfo
    return mNetworkInfo != null
            && mNetworkInfo.type == ConnectivityManager.TYPE_MOBILE
            && mNetworkInfo.isConnected
}

/**
 * 判断wifi是否连接
 *
 * @return
 */
fun Context.isWifiConnected(): Boolean {
    val activeNetInfo = connectivityManager?.activeNetworkInfo
    return activeNetInfo != null
            && activeNetInfo.type == ConnectivityManager.TYPE_WIFI
            && activeNetInfo.isConnected
}


/**
 * 是否有运行的服务
 * @receiver Context
 * @param className String
 * @return Boolean
 */
fun Context.isServiceRunning(className: String): Boolean {
    var isRunning = false
    val serviceList = activityManager?.getRunningServices(Int.MAX_VALUE)
    if (serviceList == null || serviceList.size <= 0) {
        return false
    }
    for (i in serviceList.indices) {
        if (serviceList[i] != null && serviceList[i].service != null) {
            val cName = serviceList[i].service.className
            if (cName.contains(className)) {
                isRunning = true
                break
            }
        }
    }
    return isRunning
}


/**
 * 包名判断是否为主进程
 *
 * @param context
 * @return
 */
fun Context.isMainProcess(): Boolean {
    return packageName == getProcessName()
}

/**
 * 获取进程名称
 *
 * @param context
 * @return
 */
fun Context.getProcessName(): String? {
    try {
        val runningApps = activityManager?.runningAppProcesses ?: return null
        for (proInfo in runningApps) {
            if (proInfo.pid == Process.myPid()) {
                if (proInfo.processName != null) {
                    return proInfo.processName
                }
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return null
}

/**
 * 判断当前app是否存活
 * @receiver Context
 * @param packageName String
 * @return Boolean
 */
fun Context.isAppAlive(packageName: String): Boolean {
    val processInfos = activityManager?.runningAppProcesses
    if (processInfos != null) {
        for (i in processInfos.indices) {
            if (processInfos[i].processName == packageName) {
                return true
            }
        }
    }
    return false
}

/**
 * 清楚当前所有的activity
 */
fun Context.clearAllActivity() {
    val allActivitys = getAllActivitys()
    for (i in allActivitys.indices) {
        allActivitys.get(i).finish()
    }
}

/**
 * 获取当前所有的activity
 *
 * @return activity列表
 */
@SuppressLint("PrivateApi", "DiscouragedPrivateApi")
fun Context.getAllActivitys(): List<Activity> {
    val list = ArrayList<Activity>()
    try {
        val activityThread = Class.forName("android.app.ActivityThread")
        val currentActivityThread = activityThread.getDeclaredMethod("currentActivityThread")
        currentActivityThread.isAccessible = true
        //获取主线程对象
        val activityThreadObject = currentActivityThread.invoke(null)
        val mActivitiesField = activityThread.getDeclaredField("mActivities")
        mActivitiesField.isAccessible = true
        val mActivities = mActivitiesField.get(activityThreadObject) as Map<Any, Any>
        for ((_, value) in mActivities) {
            val activityClientRecordClass = value.javaClass
            val activityField = activityClientRecordClass.getDeclaredField("activity")
            activityField.isAccessible = true
            val o = activityField.get(value)
            list.add(o as Activity)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }

    return list
}

/**
 * 注意：不能先杀掉主进程，否则逻辑代码无法继续执行，需先杀掉相关进程最后杀掉主进程
 */
fun Context.killAppProcess() {
    val mList = activityManager?.runningAppProcesses
    for (runningAppProcessInfo in mList!!) {
        if (runningAppProcessInfo.pid != Process.myPid()) {
            Process.killProcess(runningAppProcessInfo.pid)
        }
    }
    Process.killProcess(Process.myPid())
    exitProcess(0)
}

/**
 * 开启一个service之前需要判断是否开启
 * @receiver Context
 * @param className String
 * @param action Function0<Unit>
 */
fun Context.onServiceNotRunning(className: String, action: () -> Unit) {
    try {
        if (isAppInForground()) {
            val downloadPetServiceRunning: Boolean = isServiceRunning(className)
            if (!downloadPetServiceRunning) {
                action()
            }
        }
    } catch (e: IllegalStateException) {
        e.printStackTrace()
    } catch (e: SecurityException) {
        e.printStackTrace()
    }
}

/**
 * 判断app是否在前台
 * @receiver Context
 * @return Boolean
 */
fun Context.isAppInForground(): Boolean {
    val processes = activityManager?.runningAppProcesses ?: return false
    for (tmp in processes) {
        if (tmp.processName == this.packageName) {
            return tmp.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
        }
    }
    return false
}


/**
 * Sets the [text] on the clipboard
 */
fun Context.copyToClipboard(text: String, label: String = "KTX") {
    val clipData = ClipData.newPlainText(label, text)
    clipboardManager?.setPrimaryClip(clipData)
}

fun Context.dp2px(dp: Int): Int = dp2px(dp.toFloat())

fun Context.dp2px(dp: Float): Int {
    val scale = resources.displayMetrics.density
    return (dp * scale + 0.5f).toInt()
}

fun Context.px2dp(px: Int): Int = px2dp(px.toFloat()).toInt()

fun Context.px2dp(px: Float): Float {
    val scale = resources.displayMetrics.density
    return (px / scale + 0.5f)
}


/**
 * Whether horizontal layout direction of this view is from Right to Left.
 */
val Context.isRTLLayout: Boolean
    @RequiresApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    get() = resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL

/**
 * The absolute width of the available display size in pixels
 */
val Context.screenWidth
    get() = resources.displayMetrics.widthPixels

/**
 * The absolute height of the available display size in pixels
 */
val Context.screenHeight
    get() = resources.displayMetrics.heightPixels
